package com.citycloud.ccuap.tc.admin.projectfunction;

import com.citycloud.ccuap.commons.json.TreeNode;
import com.citycloud.ccuap.framework.exception.ApplicationException;
import com.citycloud.ccuap.framework.service.mybatis.MybatisServiceImpl;
import com.citycloud.ccuap.framework.util.ExcelUtil;
import com.citycloud.ccuap.tc.admin.entity.SysProjectFunction;
import com.citycloud.ccuap.tc.admin.enums.ProjectFuntionType;
import com.citycloud.ccuap.tc.admin.repository.SysProjectFunctionRepository;
import org.apache.commons.lang.StringUtils;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.ss.usermodel.WorkbookFactory;
import org.springframework.stereotype.Service;

import java.io.InputStream;
import java.util.*;

/**
 * 项目（站点）菜单业务处理实现
 *
 * @author sufeng
 */
@Service
public class ProjectFunctionService extends MybatisServiceImpl<SysProjectFunctionRepository, SysProjectFunction, String> implements IProjectFunctionService {

    /**
     * 递归获取父节点下的所有子节点
     *
     * @param pid 父节点
     * @return
     */
    private List<String> getChildNodeIdList(String pid, Long projectId) {
        List<String> childNodeIdList = new ArrayList<>();

        List<SysProjectFunction> childNodeList = repository.findByPidAndProjectId(pid, projectId);

        if (childNodeList != null) {
            for (SysProjectFunction sysPrjectFunction : childNodeList) {
                childNodeIdList.add(sysPrjectFunction.getFunId());

                //递归获取子节点
                childNodeIdList.addAll(getChildNodeIdList(sysPrjectFunction.getFunId(), projectId));
            }
        }

        return childNodeIdList;
    }

    @Override
    public void deleteNode(Long projectId, String funId) {
        List<String> childNodeIdList = getChildNodeIdList(funId, projectId);
        if (childNodeIdList.size() > 0) {
            throw new ApplicationException("您选中的菜单有子节点，不能删除！");
        }
        for (String childNodeId : childNodeIdList) {
            repository.deleteByProjectIdAndFunId(projectId, childNodeId);
        }
        repository.deleteByProjectIdAndFunId(projectId, funId);
    }

    @Override
    public void deleteNodeList(Long projectId, List<String> funIdList) {
        for (String funId : funIdList) {
            deleteNode(projectId, funId);
        }
    }

    @Override
    public List<TreeNode> findNextChildNodeTree(String pid, Long projectId) {
        List<TreeNode> treeList = new ArrayList<TreeNode>();

        List<SysProjectFunction> nodeList;
        if (pid == null) {
            nodeList = repository.findByPidNullAndProjectIdOrderByOrderNo(projectId);
        } else {
            nodeList = repository.findByPidAndProjectIdOrderByOrderNo(pid, projectId);
        }
        if (nodeList != null) {
            for (SysProjectFunction sysPrjectFunction : nodeList) {
                TreeNode node = new TreeNode();
                node.setId(sysPrjectFunction.getFunId().toString());
                node.setText(sysPrjectFunction.getFunName());
                node.setExpanded(true);
                boolean isLeaf = !hasChildNode(sysPrjectFunction.getFunId(), projectId);
                node.setLeaf(isLeaf);

                treeList.add(node);
            }
        }

        return treeList;
    }

    @Override
    public void updateFullPathBatch(Long projectId, String funId, String existFullPath, String fullPath) {

        List<SysProjectFunction> funList = getAllChildList(projectId, funId);
        for (SysProjectFunction sysFunction : funList) {
            String path = sysFunction.getFullPath();
            if (StringUtils.isBlank(path)) {
                throw new ApplicationException("全路径为空");
            }
            sysFunction.setFullPath(path.replaceFirst(existFullPath, fullPath));
            repository.save(sysFunction);
        }
    }

    @Override
    public List<SysProjectFunction> getAllChildList(Long projectId, String funId) {
        List<SysProjectFunction> allChildList = new ArrayList<>();

        List<SysProjectFunction> childList = repository.findByPidAndProjectIdOrderByOrderNo(funId, projectId);

        if (childList != null) {
            for (SysProjectFunction sysFunction : childList) {
                allChildList.add(sysFunction);

                // 递归获取子节点
                allChildList.addAll(getAllChildList(projectId, sysFunction.getFunId()));
            }
        }

        return allChildList;
    }

    @Override
    public List<TreeNode> findNodeTreeByName(String funName, Long projectId) {
        List<TreeNode> treeList = new ArrayList<>();
        List<SysProjectFunction> nodeList;

        nodeList = repository.findByProjectIdAndFullPathContainingOrderByOrderNo(projectId, funName);

        Set<String> funSet = new HashSet<>();
        if (nodeList != null) {
            for (SysProjectFunction sysFunction : nodeList) {
                String[] pathList = sysFunction.getFullPath().split("/");
                int j = 0;
                for (int i = 0; i < pathList.length; i++) {
                    String name = pathList[i];
                    if (name.contains(funName)) {
                        j = i + 1;
                    }
                }

                for (int i = 0; i < j; i++) {
                    String name = pathList[i];
                    funSet.add(name);
                }

            }
        }
        Iterator<String> iterator = funSet.iterator();

        List<SysProjectFunction> todoList = new ArrayList<>();
        while (iterator.hasNext()) {
            String name = iterator.next();
            List<SysProjectFunction> funList = repository.findByProjectIdAndFunNameOrderByOrderNo(projectId, name);
            for (SysProjectFunction sysFunction : funList) {
                todoList.add(sysFunction);
            }
        }

        for (SysProjectFunction sysFunction : todoList) {
            if (sysFunction.getPid() == null) {
                TreeNode node = new TreeNode();
                node.setId(sysFunction.getFunId().toString());
                node.setText(sysFunction.getFunName());
                node.setExpanded(true);
                treeList.add(findChildren(node, todoList, projectId));
            }
        }
        return treeList;
    }


    @Override
    public void importProjectFunction(InputStream is,Long projectId) {
        Workbook workbook = null;
        SysProjectFunction spf=null;
        Map<String,String> namePidMap=new HashMap<>(16);
        Map<String,String> pidNameMap=new HashMap<>(16);
        List<SysProjectFunction> sysProjectFunctions=new ArrayList<>();
        try {
            workbook = WorkbookFactory.create(is);
            for (int numSheet = 0; numSheet < workbook.getNumberOfSheets(); ++numSheet) {
                Sheet xssfSheet = workbook.getSheetAt(numSheet);
                if (xssfSheet != null) {
                    for (int rowNum = 1; rowNum <= xssfSheet.getLastRowNum(); ++rowNum) {
                        Row xssfRow = xssfSheet.getRow(rowNum);
                        if (xssfRow != null) {
                            spf=new SysProjectFunction();
                            String fMenu=(String) ExcelUtil.getCellValue(xssfRow.getCell(0));
                            String menuType=(String)ExcelUtil.getCellValue(xssfRow.getCell(1));
                            String menuName=(String)ExcelUtil.getCellValue(xssfRow.getCell(2));
                            String href=(String)ExcelUtil.getCellValue(xssfRow.getCell(3));
                            String order=(String)ExcelUtil.getCellValue(xssfRow.getCell(4));
                            String help=(String)ExcelUtil.getCellValue(xssfRow.getCell(5));
                            String window=(String)ExcelUtil.getCellValue(xssfRow.getCell(6));
                            String log=(String)ExcelUtil.getCellValue(xssfRow.getCell(7));
                            String icon=(String)ExcelUtil.getCellValue(xssfRow.getCell(8));
                            String remark=(String)ExcelUtil.getCellValue(xssfRow.getCell(9));

                            spf.setProjectId(projectId);
                            String funId=UUID.randomUUID().toString().replace("-", "")+"_"+projectId;
                            spf.setFunId(funId);


                            if(StringUtils.isNotEmpty(fMenu)){
                                String pid = namePidMap.get(fMenu);
                                if(StringUtils.isNotEmpty(pid)){
                                    spf.setPid(pid);
                                }else{
                                    throw new RuntimeException("第"+rowNum+"行，父菜单不存在");
                                }
                                //非顶级菜单为父菜单
                                namePidMap.putIfAbsent(menuName,funId);
                            }else{
                                //顶级菜单 为父菜单
                                namePidMap.putIfAbsent(menuName, funId);
                            }
                            //获取pid对应的菜单名称 用于形成全路径
                            pidNameMap.put(funId,menuName);

                            if(!StringUtils.isNotEmpty(menuType)){
                                throw new RuntimeException("第"+rowNum+"行，菜单类型不能为空");
                            }
                            short type = ProjectFuntionType.getValueByType(menuType);
                            if(type==-1){
                                throw new RuntimeException("第"+rowNum+"行，无效的菜单类型");
                            }
                            spf.setFunType(type);

                            if(!StringUtils.isNotEmpty(menuName)){
                                throw new RuntimeException("第"+rowNum+"行，菜单名称不能为空");
                            }
                            spf.setFunName(menuName);

                            spf.setLocation(href);
                            try{
                                spf.setOrderNo(Long.parseLong(order));
                            }catch (Exception e){
                                spf.setOrderNo(null);
                            }
                            if(type==2){
                                spf.setHelpUrl(help);
                                if(StringUtils.isNotEmpty(window)){
                                    spf.setOpenNew("是".equals(window)?true:false);
                                }else{
                                    spf.setOpenNew(false);
                                }
                            }else{
                                spf.setOpenNew(false);
                            }
                            if(StringUtils.isNotEmpty(log)){
                                spf.setLogFlag("是".equals(log)?(short)1:(short)0);
                            }else{
                                spf.setLogFlag((short)0);
                            }
                            spf.setIcon(icon);
                            spf.setRemark(remark);
                            spf.setVersion(0);
                            StringBuffer path=new StringBuffer();
                            String fullPath = getPath(namePidMap, fMenu,path,sysProjectFunctions,pidNameMap);
                            spf.setFullPath(fullPath+menuName);
                            sysProjectFunctions.add(spf);
                        }
                    }
                }
            }
            repository.deleteByProjectId(projectId);
            this.insert(sysProjectFunctions);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }




    private String getPath(Map<String,String> map,String fmenu,StringBuffer fullPath,List<SysProjectFunction> list,Map<String,String> pidNameMap){
        String pid = map.get(fmenu);
        if(pid!=null){
            fullPath.insert(0,fmenu+"/");
            for (SysProjectFunction sysProjectFunction: list) {
                String funId = sysProjectFunction.getFunId();
                if(pid.equals(funId)){
                    String fPid=sysProjectFunction.getPid();
                    String fName=pidNameMap.get(fPid);
                    if(StringUtils.isNotEmpty(fName)){
                        getPath(map,fName,fullPath,list,pidNameMap);
                    }
                }
            }
        }
        return fullPath.toString();
   }

    /**
     * 递归查找子节点
     *
     * @param treeNode
     * @param funList
     * @return TreeNode
     */
    private TreeNode findChildren(TreeNode treeNode, List<SysProjectFunction> funList, Long projectId) {
        for (SysProjectFunction sysFunction : funList) {
            if (sysFunction.getPid() != null && treeNode.getId().equals(sysFunction.getPid())) {
                if (treeNode.getChildren() == null) {
                    treeNode.setChildren(new ArrayList<TreeNode>());
                }
                TreeNode node = new TreeNode();
                node.setId(sysFunction.getFunId().toString());
                node.setText(sysFunction.getFunName());
                node.setExpanded(true);
                boolean isLeaf = !hasChildNode(sysFunction.getFunId(), projectId);
                node.setLeaf(isLeaf);
                treeNode.getChildren().add(findChildren(node, funList, projectId));
            }
        }
        return treeNode;
    }

    private boolean hasChildNode(String pid, Long projectId) {
        Long count = repository.countByPidAndProjectId(pid, projectId);

        if (count == 0) {
            return false;
        } else {
            return true;
        }
    }
}